---
layout: default
title: 文章广场
---
<style>
    #search-input {
        width: 70%;
        margin-left: 20px;
        z-index: 1000;
        background-color: rgba(255, 255, 255, 0.95);
        border: groove #cccccc;
        border-radius: 25px;
        height: 50px;
        font-size: 25px;
        padding-left: 20px;
    }

    #search-class {
        margin-left: 20px;
        width: 90%;
        max-height: 300px;
        overflow-y: auto;
        z-index: 1000;
        background-color: rgba(255, 255, 255, 0.95);
        border: groove #cccccc;
        border-radius: 25px;
        font-size: 25px;
        padding-left: 20px;
    }

    #search {
        display: none;
    }

    #search-button {
        width: 50px;
        height: 50px;
        background-color: transparent;
        border: none;
        cursor: pointer;
        padding-top: 10px;
        right: 0;
    }

    .class-select {
        color: black;
    }

    #search-class li::marker {
        display: none;
        content: "";
    }

    .blog-item {
        margin: 10px 0;
        padding: 10px;
        border: 1px solid #ccc;
        border-radius: 5px;
        background-color: #f9f9f9;
        color: black;
    }

    #blog-container {
        position: fixed;
        right: 100%;
        top: 100px;
        bottom: 100%;
        overflow: auto;
        padding: 10px;
        background: #ffffff;
        color: #000000;
        border: groove #cccccc 3px;
        border-radius: 25px;
        z-index: 1000;
    }
</style>
<button id="showSearch-button">筛选器</button>
<div id="search">
    <div style="height: 50px;">
        <input id="search-input" type="text" placeholder="搜索文章..."/>
        <button onclick="updateSearch();" title="搜索" id="search-button">
            <img src="{{ site.imgs[0].link }}" alt="搜索" title="搜索"
                 style="width: 50px; height: 50px;">
        </button>
        <input id="search-input-contents" type="checkbox" onclick="updateSearch();"/>
        <label for="search-input-contents">搜索内容</label>
    </div>
    <div id="search-class"></div>
</div>
{% include BlogsCmp.html %}
<select id="cmp" onchange="updateSearch()">
</select>
<select id="key" onchange="updateSearch()">
</select>
<div id="search-container">
    <p>加载中...</p>
</div>
<div id="blog-container">
    <div id="blog-dec"></div>
    <iframe id="blog-frame"></iframe>
</div>
<script>
    window.title = $(document).attr('title');
</script>
<script>
    changeBgText();
    changeTime();
    const searchInput = $("#search-input");

    function getSearch() {
        const search = getParam("search");
        if (search) {
            searchInput.val(search);
        } else {
            const cookieSearch = getCookie("search");
            if (cookieSearch) {
                searchInput.val(cookieSearch);
            }
        }
        updateSearch();
    }

    function getSelectClass() {
        const selectClass = getParam("class");
        if (selectClass) {
            const classes = selectClass.split(',');
            classes.forEach((item) => {
                const checkbox = $("#search-class").find(`input[id="/所有分类${item}"]`);
                checkbox.click();
                checksClass.add(item);
            });
        } else {
            let cookieClass = getCookie("class");
            if (!cookieClass) {
                cookieClass = getClasses();
                setCookie("class", cookieClass);
            }
            cookieClass.forEach((item) => {
                const checkbox = $("#search-class").find(`input[id="/所有分类${item}"]`);
                checkbox.click();
                checksClass.add(item);
            });
        }
        updateSearch();
    }

    function InitSort() {
        const keySelect = $("#key");
        const cmpSelect = $("#cmp");

        // 清空现有选项
        keySelect.empty();
        cmpSelect.empty();

        // 添加键选项
        for (const key in Keys) {
            const option = $("<option>");
            option.val(key);
            option.text(KeyNames[key]);
            keySelect.append(option);
        }

        // 添加比较选项
        for (const cmp in Cmps) {
            const option = $("<option>");
            option.val(cmp);
            option.text(CmpNames[cmp]);
            cmpSelect.append(option);
        }
    }

    function ShowSearch() {
        const search = $("#search");
        const searchButton = $("#showSearch-button");
        if (search.css("display") === "none" || search.css("display") === "") {
            search.show();
            searchButton.html("隐藏筛选器");
        } else {
            search.hide();
            searchButton.html("筛选器");
        }
        execute();
    }

    $(document).ready(() => {
        $("#showSearch-button").on("click", ShowSearch);
    });

    function Check(checkbox) {
        const childrenCheckboxes = $(checkbox).children().eq(2).find('input');
        let checkedCount = 0;
        let uncheckedCount = 0;
        childrenCheckboxes.each((index, child) => {
            if ($(child).prop("checked")) {
                checkedCount++;
            } else {
                uncheckedCount++;
            }
        });
        if (uncheckedCount === 0) {
            return 1; // 全部未选中
        } else if (checkedCount === 0) {
            return 0; // 全部选中
        } else {
            return -1; // 部分选中
        }
    }

    let checksClass = new Set();
    window.checksClass = checksClass;
    const blogFrame = $("#blog-frame");
    const blogDec = $("#blog-dec");

    function loadSearch() {
        return loadJson("../search.json");
    }

    function setCookieSearch() {
        const search = searchInput.val();
        const selectClass = checksClass;
        setCookie("search", search);
        setCookie("class", selectClass);
    }

    async function updateSearch() {
        const searchContainer = $("#search-container");
        searchContainer.html('搜索中……');
        const Key = Keys[$("#key").val()];
        const Cmp = Cmps[$("#cmp").val()];
        const blogs = await loadSearch();
        const searchBlogs = [];
        // console.log("updateSearch", checksClass);
        for (const blog of blogs) {
            // console.log("look at", blog);
            if (checksClass.has(blog.class)) {
                blog.title = translateText(blog.title);
                searchBlogs.push(blog);
            }
        }
        searchBlogs.sort((a, b) => {
            // console.log(a, b, Key(a), Key(b), Cmp(Key(a), Key(b)), Key, Cmp);
            return Cmp(Key(a), Key(b));
        });
        searchContainer.empty(); // 清空现有内容
        blogFrame.attr("src", '');
        blogDec.empty();
        if (searchBlogs.length === 0) {
            searchContainer.html('<p>没有找到符合条件的文章</p>');
        } else {
            searchBlogs.forEach(blog => {
                const blogElement = $("<div>");
                blogElement.addClass("blog-item");
                blogElement.html(`
                    <a href="${blog.url}" target="_blank">
                        <h2>${blog.title}</h2>
                        <p>分类: ${blog.class}</p>
                        <p>日期: ${blog.date}</p>
                    </a>
                `);
                const a = blogElement.find("a");
                searchContainer.append(blogElement);
                blogElement.on("mouseenter", () => {
                    blogFrame.attr("src", blog.url);
                    blogDec.html(a.html());
                });
            });
            $(document).attr('title', `${searchInput.val()} - ${window.title}`);
        }
        execute();
        setCookieSearch();
        blogFrame.html('<p>悬停文章预览</p>');
    }

    function getClass(className) {
        return className.replace("/所有分类", "");
    }

    function checkCheckbox(checkbox, childStates) {
        checkbox.indeterminate = false;
        const children = $(checkbox).children().eq(2).find('input');
        const checked = $(checkbox).children().eq(0).prop("checked");
        if (checked) {
            checkbox.dataUOC = true;
        }
        children.each((index, child) => {
            const div = $(child).parent();
            div.dataUOC = false;
            if (checked) {
                childStates.set(div[0], $(child).prop("checked"));
                $(child).prop("checked", true);
            } else {
                if (!checkbox.dataUOC) {
                    childStates.set(div[0], false);
                }
                $(child).prop("checked", childStates.get(div[0]));
            }
            setCheckClass(div[0]);
        });
        if (!checked) {
            checkbox.dataUOC = false;
        }
        setCheckClass(checkbox);
    }

    function setCheckClass(checkbox) {
        const state = $(checkbox).children().eq(0).prop("checked");
        const className = getClass($(checkbox).children().eq(0).val());
        if (state) {
            checksClass.add(className);
        } else {
            checksClass.delete(className);
        }
    }

    function setCheckbox(checkbox) {
        setCheckClass(checkbox);
        const parent = $(checkbox).parent().parent().parent();
        if (parent.length && parent.attr("id") !== "search-class") {
            const parentCheckbox = parent.find("input");
            const checkState = Check(parent[0]);
            if (checkState === 1) {
                parentCheckbox.prop("checked", true);
                parentCheckbox.prop("indeterminate", false);
            } else if (checkState === 0) {
                parentCheckbox.prop("checked", false);
                parentCheckbox.prop("indeterminate", false);
            } else {
                parentCheckbox.prop("checked", false);
                parentCheckbox.prop("indeterminate", true);
            }
            setCheckbox(parent[0]);
        }
    }

    function Option(class_, base_class) {
        base_class += "/" + class_.name;
        let alloptions = $('<div>').get(0);
        let optionInput = $('<input>').prop({type: 'checkbox', checked: false, value: base_class, id: base_class}).get(0);
        $(alloptions).append(optionInput);
        let optionLabel = $('<label>').addClass("class-select").attr("for", base_class).text(class_.name).get(0);
        $(alloptions).append(optionLabel);
        const children = class_.children;
        let children_list = $('<ul>').get(0);
        for (let i in children) {
            const class_ = children[i];
            let children_option = $('<li>').get(0);
            $(children_option).append(Option(class_, base_class));
            $(children_list).append(children_option);
        }
        $(alloptions).append(children_list);
        // 保存子节点原始状态
        const childStates = new WeakMap();
        $(optionInput).on('click', e => {
            const parent = $(e.target).parent().get(0);
            checkCheckbox(parent, childStates);
            setCheckbox(parent);
            updateSearch();
        });
        return alloptions;
    }

    function getClasses() {
        return loadSearch().then(posts => {
            // 创建分类树结构
            const classTree = {name: "所有分类", children: []};

            posts.forEach(post => {
                const classPath = post.class.split('/').filter(Boolean);
                let currentLevel = classTree.children;

                classPath.forEach(className => {
                    let existingNode = currentLevel.find(node => node.name === className);
                    if (!existingNode) {
                        existingNode = {name: className, children: []};
                        currentLevel.push(existingNode);
                    }
                    currentLevel = existingNode.children;
                });
            });

            return classTree;
        });
    }
    // 修改InitSelect中的调用方式
    async function InitSelect() {
        const classes = await getClasses();
        const select = $("#search-class");
        select.empty();
        const ul = $('<ul>').get(0);
        select.append(ul);
        const li = $('<li>').get(0);
        const option = Option(classes, "");
        $(li).append(option);
        $(ul).append(li);
        getSelectClass();
        getSearch();
    }

    $(document).ready(InitSelect);
    InitSort();
    searchInput.on("keydown", e => {
        if (e.key === "Enter") {
            updateSearch();
        }
    });
</script>
